package com.geezdata.cps.sdk3rd.kongming;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.geezdata.cps.base.enums.ErrorCode;
import com.geezdata.cps.base.response.BaseResponse;
import com.geezdata.cps.base.utils.HttpClientUtil;
import com.geezdata.cps.base.utils.JaxbUtil;
import com.geezdata.cps.base.utils.Md5Util;
import com.geezdata.cps.sdk3rd.kongming.request.KongmingRequest;
import com.geezdata.cps.sdk3rd.kongming.response.KongmingResult;

public class KongmingDefaultClient implements KongmingClient {
	private static Logger logger = LoggerFactory.getLogger(KongmingDefaultClient.class);

    private String serverUrl; // 要调用的服务的url（serverUrl后面要加上时间戳参数，避免请求缓存的影响）
    private String appKey; // appkey 应用的唯一标识，对应一个业务组
    private String appSecret; // appSecret 该业务组的授权密钥

    public KongmingDefaultClient(String serverUrl, String appKey, String appSecret) {
        this.appKey = appKey;
        this.appSecret = appSecret;
        this.serverUrl = serverUrl;
    }

    public <T extends KongmingResult> BaseResponse<T> execute(KongmingRequest<T> request) {
        // 1、检查serverUrl、appkey、appsert参数是否有空
        if( StringUtils.isEmpty(serverUrl) || StringUtils.isEmpty(appKey) 
                || StringUtils.isEmpty(appSecret)  ){
        	return BaseResponse.error(ErrorCode.INVALID_PARAMS.getCode(), 
        			ErrorCode.INVALID_PARAMS.getDesc());
        }
        
        // 2、Request及自身参数检查
        if(request == null){
        	return BaseResponse.error(ErrorCode.INVALID_PARAMS.getCode(), 
        			ErrorCode.INVALID_PARAMS.getDesc());
        }
        
        // 5、发送报文并获取响应的报文串
        String rspStr = null;
        try {
            rspStr = HttpClientUtil.post(serverUrl + request.getMethodName(), prepareHttpParams(request));
        } catch (Exception e) {
        	return BaseResponse.error(ErrorCode.HTTP_EXCEPTION.getCode(), e.getMessage());
        }  
        
        if(StringUtils.isEmpty(rspStr)){
            logger.info("resp str is empty");
            return BaseResponse.error(ErrorCode.HTTP_EXCEPTION.getCode(), "resp str is empty");
        }
        
        // 6、将返回封装成对应的Response
        T kongmingResult = null;
        try {
            if(rspStr.contains("xml")){
                String xmlRspStr = rspStr.replaceAll("\\?>", "\\?><response>") + "</response>";
                kongmingResult = (T)JaxbUtil.converyToJavaBean(xmlRspStr, request.getResponseClass()) ;
            } else {
            	return BaseResponse.error(ErrorCode.HTTP_EXCEPTION.getCode(), rspStr);
            }
        } catch (Exception e) {
            logger.error("resp transfer error", e);
            return BaseResponse.error(ErrorCode.HTTP_EXCEPTION.getCode(), e.getMessage());
        }

        return (BaseResponse<T>) BaseResponse.success(kongmingResult);
    }
    
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private Map<String, Object> prepareHttpParams(KongmingRequest request) {
        Map<String, Object> httpParams = new TreeMap<String, Object>();
        Map<String, Object> appParams = request.getAppParams();
        Iterator<String> it = appParams.keySet().iterator();
        while (it.hasNext()) {
            String key = it.next();
            Object value = appParams.get(key);
            httpParams.put(key, value);
        }
        
        String unixtime = String.valueOf(new Date().getTime()/1000);
        Map<String, String> signMap = new TreeMap<String, String>();
        signMap.put("ip", "");
        signMap.put("key", appKey);
        signMap.put("unixtime", unixtime);
        httpParams.put("token", createSign(signMap) );  //这里的sign就是token
        httpParams.put("unixtime", unixtime);
 
        return httpParams;
    }
    
    private String createSign(Map<String, String> requestParamsMap) {
        Object[] keyArray = requestParamsMap.keySet().toArray();
        List<String> keyList = new ArrayList<String>();
        for (int i = 0; i < keyArray.length; i++) {
            keyList.add((String) keyArray[i]);
        }
        Collections.sort(keyList);
        String signContent = "";

        for (String key : keyList) {
            signContent +=  requestParamsMap.get(key);
        }
        return Md5Util.md5(signContent);
    }
}
